<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta
            http-equiv="Content-Type"
            content="text/html; charset=utf-8"
        />
        <meta name="viewport" content="width=device-width, initial-scale=1" />

        <title>Installation &mdash; Python Slack SDK</title>

        <!-- Google Tag Manager -->
        <script>
            (function(w, d, s, l, i) {
                w[l] = w[l] || [];
                w[l].push({
                    'gtm.start': new Date().getTime(),
                    event: 'gtm.js'
                });
                var f = d.getElementsByTagName(s)[0],
                    j = d.createElement(s),
                    dl = l != 'dataLayer' ? '&l=' + l : '';
                j.async = true;
                j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
                f.parentNode.insertBefore(j, f);
            })(window, document, 'script', 'dataLayer', 'GTM-KFZ5MK7');
        </script>
        <!-- End Google Tag Manager -->
        
        <link
            href="https://a.slack-edge.com/4f227/style/rollup-slack_kit_legacy_adapters.css"
            rel="stylesheet"
            type="text/css"
        />
        <link
            href="https://a.slack-edge.com/3e02c0/style/rollup-api_site.css"
            rel="stylesheet"
            type="text/css"
        />
        <link
            rel="stylesheet"
            href=".././assets/default.css"
            type="text/css"
        />
        <link
            rel="stylesheet"
            href=".././assets/pygments.css"
            type="text/css"
        />
        <link
            rel="stylesheet"
            href=".././assets/docs.css"
            type="text/css"
        />
        <link
            id="favicon"
            rel="shortcut icon"
            href="https://a.slack-edge.com/4f28/img/icons/favicon-32.png"
            type="image/png"
        />
        <link
            rel="top"
            title="Python Slack SDK 1.0.1 documentation"
            href="../index.html"
        />
    </head>

    <body class="api light_theme">
        <!-- Google Tag Manager (noscript) -->
        <noscript
            ><iframe
                src="https://www.googletagmanager.com/ns.html?id=GTM-KFZ5MK7"
                height="0"
                width="0"
                style="display:none;visibility:hidden"
            ></iframe
        ></noscript>
        <!-- End Google Tag Manager (noscript) -->
        <header>
            <a id="menu_toggle" class="no_transition show_on_mobile">
                <span class="menu_icon"></span>
                <span class="vert_divider"></span>
            </a>
            <a
                href="https://api.slack.com/"
                id="header_logo"
                class="api hide_on_mobile"
                style="float:left; display: inline-block;"
            >
                <img
                    alt="Slack API"
                    src="https://a.slack-edge.com/3026cb/img/slack_api_logo_vogue.png"
                    style="width: 225px; padding-right: 25px; border-right: 1px solid #DDD;"
                />
            </a>
            <span
                style="display: inline-block; padding-left: 20px; margin-top: 25px; font-weight: bold;"
            >
                <a style="color: #555459;" href="./index.html">Python Slack SDK</a>
            </span>
            <div class="header_nav">
                <a
                    href="https://github.com/SlackAPI/python-slack-sdk"
                    class="btn header_btn float_right"
                    data-qa="go_to_slack"
                    >Go to GitHub</a
                >
            </div>
        </header>
        

        <div id="page">
            <div id="page_contents" class="clearfix">
                <!-- Sidebar Content -->
                <nav id="api_nav" class="col span_1_of_4">
                    <div id="api_sections">
                         <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../index.html">Python Slack SDK</a></li>
<li class="toctree-l1"><a class="reference internal" href="../v3-migration/index.html">Migration Guide</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../v3-migration/index.html#from-slackclient-2-x">From slackclient 2.x</a></li>
<li class="toctree-l2"><a class="reference internal" href="../v3-migration/index.html#from-slackclient-1-x">From slackclient 1.x</a></li>
</ul>
</li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Installation</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#access-tokens">Access Tokens</a></li>
<li class="toctree-l2"><a class="reference internal" href="#workspace-installations">Workspace Installations</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../web/index.html">Web Client</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../web/index.html#messaging">Messaging</a></li>
<li class="toctree-l2"><a class="reference internal" href="../web/index.html#files">Files</a></li>
<li class="toctree-l2"><a class="reference internal" href="../web/index.html#conversations">Conversations</a></li>
<li class="toctree-l2"><a class="reference internal" href="../web/index.html#modals">Modals</a></li>
<li class="toctree-l2"><a class="reference internal" href="../web/index.html#rate-limits">Rate Limits</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../web/index.html#calling-any-api-methods">Calling any API methods</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../web/index.html#asyncwebclient">AsyncWebClient</a></li>
<li class="toctree-l2"><a class="reference internal" href="../web/index.html#retryhandler">RetryHandler</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../webhook/index.html">Webhook Client</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../webhook/index.html#id1">Incoming Webhooks</a></li>
<li class="toctree-l2"><a class="reference internal" href="../webhook/index.html#response-url">response_url</a></li>
<li class="toctree-l2"><a class="reference internal" href="../webhook/index.html#asyncwebhookclient">AsyncWebhookClient</a></li>
<li class="toctree-l2"><a class="reference internal" href="../webhook/index.html#retryhandler">RetryHandler</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../socket-mode/index.html">Socket Mode Client</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../socket-mode/index.html#socketmodeclient">SocketModeClient</a></li>
<li class="toctree-l2"><a class="reference internal" href="../socket-mode/index.html#supported-libraries">Supported Libraries</a></li>
<li class="toctree-l2"><a class="reference internal" href="../socket-mode/index.html#asyncio-based-libraries">Asyncio Based Libraries</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../oauth/index.html">OAuth Modules</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../oauth/index.html#app-installation-flow">App Installation Flow</a></li>
<li class="toctree-l2"><a class="reference internal" href="../oauth/index.html#token-lookup">Token Lookup</a></li>
<li class="toctree-l2"><a class="reference internal" href="../oauth/index.html#sign-in-with-slack">Sign in with Slack</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../audit-logs/index.html">Audit Logs API Client</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../audit-logs/index.html#auditlogsclient">AuditLogsClient</a></li>
<li class="toctree-l2"><a class="reference internal" href="../audit-logs/index.html#asyncauditlogsclient">AsyncAuditLogsClient</a></li>
<li class="toctree-l2"><a class="reference internal" href="../audit-logs/index.html#retryhandler">RetryHandler</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../scim/index.html">SCIM API Client</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../scim/index.html#scimclient">SCIMClient</a></li>
<li class="toctree-l2"><a class="reference internal" href="../scim/index.html#asyncscimclient">AsyncSCIMClient</a></li>
<li class="toctree-l2"><a class="reference internal" href="../scim/index.html#retryhandler">RetryHandler</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../real_time_messaging.html">RTM Client</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../real_time_messaging.html#real-time-messaging-rtm">Real Time Messaging (RTM)</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../faq.html">FAQ</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../faq.html#python-documents">Python Documents</a></li>
<li class="toctree-l2"><a class="reference internal" href="../faq.html#installation-issues">Installation Issues</a></li>
<li class="toctree-l2"><a class="reference internal" href="../faq.html#bug-report">Bug Report</a></li>
<li class="toctree-l2"><a class="reference internal" href="../faq.html#feature-requests">Feature Requests</a></li>
<li class="toctree-l2"><a class="reference internal" href="../faq.html#contributions">Contributions</a></li>
<li class="toctree-l2"><a class="reference internal" href="../faq.html#documentation">Documentation</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../about.html">About</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../about.html#product-name">Python Slack SDK</a></li>
</ul>
</li>
</ul>


<div id="footer">

        <ul id="footer_nav">
                <li><a href="https://github.com/SlackAPI/python-slack-sdk/blob/main/LICENSE">License</a></li>
                <li><a href="https://slackhq.github.io/code-of-conduct">Code of Conduct</a></li>
                <li><a href="https://github.com/slackapi/python-slack-sdk/blob/main/.github/contributing.md">Contributing</a></li>
                <li><a href="https://docs.google.com/a/slack-corp.com/forms/d/e/1FAIpQLSfzjVoCM7ohBnjWf7eDYQxzti1EPpinsIJQA5RAUBwJKRUQHg/viewform">Contributor License Agreement</a></li>
        </ul>

        <p id="footer_signature">Made with <i class="ts_icon ts_icon_heart"></i> by Slack<br/>and our Lovely
                Community
        </p>
</div> 
                    </div>
                </nav>
                <!-- /Sidebar Content -->

                <!-- Body Content -->
                <div class="col span_3_of_4">
                    <!-- <div class="section-title">Installation</div> -->
                    <div class="card">
  <section id="installation">
<h1>Installation<a class="headerlink" href="#installation" title="Link to this heading">¶</a></h1>
<section id="access-tokens">
<span id="handling-tokens"></span><h2>Access Tokens<a class="headerlink" href="#access-tokens" title="Link to this heading">¶</a></h2>
<p><strong>Keeping access tokens safe</strong></p>
<p>The OAuth token you use to call the Slack API has access to the data on the workspace where it is installed.</p>
<p>Depending on the scopes granted to the token, it potentially has the ability to read and write data. Treat these tokens just as you would a password – don’t publish them, don’t check them into source code, don’t share them with others.</p>
<p>🚫Avoid this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">token</span> <span class="o">=</span> <span class="s1">&#39;xoxb-111-222-xxxxx&#39;</span>
</pre></div>
</div>
<p>We recommend you pass tokens in as environment variables, or persist them in a database that is accessed at runtime. You can add a token to the environment by starting your app as:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">SLACK_BOT_TOKEN</span><span class="o">=</span><span class="s2">&quot;xoxb-111-222-xxxxx&quot;</span> <span class="n">python</span> <span class="n">myapp</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>Then retrieve the key with:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
<span class="n">SLACK_BOT_TOKEN</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;SLACK_BOT_TOKEN&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>For additional information, please see our <a class="reference external" href="https://api.slack.com/authentication/best-practices">Safely Storing Credentials</a> page.</p>
</section>
<section id="workspace-installations">
<h2>Workspace Installations<a class="headerlink" href="#workspace-installations" title="Link to this heading">¶</a></h2>
<p><strong>Single Workspace Install</strong></p>
<p>If you’re building an application for a single Slack workspace, there’s no need to build out the entire OAuth flow.</p>
<p>Once you’ve setup your features, click on the <strong>Install App to Team</strong> button found on the <strong>Install App</strong> page.
If you add new permission scopes or Slack app features after an app has been installed, you must reinstall the app to
your workspace for changes to take effect.</p>
<p>For additional information, see the <a class="reference external" href="https://api.slack.com/start/overview#installing_distributing">Installing Apps</a> of our <a class="reference external" href="https://api.slack.com/start">Building Slack apps</a> page.</p>
<p><strong>Multiple Workspace Install</strong></p>
<p>If you intend for an app to be installed on multiple Slack workspaces, you will need to handle this installation via the industry-standard OAuth protocol. You can read more about <a class="reference external" href="https://api.slack.com/authentication/oauth-v2">how Slack handles Oauth</a>.</p>
<p>(The OAuth exchange is facilitated via HTTP and requires a webserver; in this example, we’ll use <a class="reference external" href="https://flask.palletsprojects.com/">Flask</a>.)</p>
<p>To configure your app for OAuth, you’ll need a client ID, a client secret, and a set of one or more scopes that will be applied to the token once it is granted. The client ID and client secret are available from your <a class="reference external" href="https://api.slack.com/apps">app’s configuration page</a>. The scopes are determined by the functionality of the app – every method you wish to access has a corresponding scope and your app will need to request that scope in order to be able to access the method. Review Slack’s <a class="reference external" href="https://api.slack.com/scopes">full list of OAuth scopes</a>.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">slack_sdk</span> <span class="kn">import</span> <span class="n">WebClient</span>
<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">request</span>

<span class="n">client_id</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;SLACK_CLIENT_ID&quot;</span><span class="p">]</span>
<span class="n">client_secret</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;SLACK_CLIENT_SECRET&quot;</span><span class="p">]</span>
<span class="n">oauth_scope</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;SLACK_SCOPES&quot;</span><span class="p">]</span>

<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
</pre></div>
</div>
<p><strong>The OAuth initiation link</strong></p>
<p>To begin the OAuth flow that will install your app on a workspace, you’ll need to provide the user with a link to Slack’s OAuth page. This can be a simple link to <code class="docutils literal notranslate"><span class="pre">https://slack.com/oauth/v2/authorize</span></code> with <code class="docutils literal notranslate"><span class="pre">scope</span></code> and <code class="docutils literal notranslate"><span class="pre">client_id</span></code> query parameters, or you can use our pre-built <a class="reference external" href="https://api.slack.com/docs/slack-button">Add to Slack button</a> to do all the work for you.</p>
<p>This link directs the user to Slack’s OAuth acceptance page, where the user will review and accept or refuse the permissions your app is requesting as defined by the scope(s).</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/slack/install&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;GET&quot;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">pre_install</span><span class="p">():</span>
    <span class="n">state</span> <span class="o">=</span> <span class="s2">&quot;randomly-generated-one-time-value&quot;</span>
    <span class="k">return</span> <span class="s1">&#39;&lt;a href=&quot;https://slack.com/oauth/v2/authorize?&#39;</span> \
        <span class="sa">f</span><span class="s1">&#39;scope=</span><span class="si">{</span><span class="n">oauth_scope</span><span class="si">}</span><span class="s1">&amp;client_id=</span><span class="si">{</span><span class="n">client_id</span><span class="si">}</span><span class="s1">&amp;state=</span><span class="si">{</span><span class="n">state</span><span class="si">}</span><span class="s1">&quot;&gt;&#39;</span> \
        <span class="s1">&#39;Add to Slack&lt;/a&gt;&#39;</span>
</pre></div>
</div>
<p><strong>The OAuth completion page</strong></p>
<p>Once the user has agreed to the permissions you’ve requested, Slack will redirect the user to your auth completion page, which includes a <code class="docutils literal notranslate"><span class="pre">code</span></code> query string param. You’ll use the <code class="docutils literal notranslate"><span class="pre">code</span></code> param to call the <code class="docutils literal notranslate"><span class="pre">oauth.v2.access</span></code> <a class="reference external" href="https://api.slack.com/methods/oauth.v2.access">endpoint</a> that will finally grant you the token.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/slack/oauth_redirect&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;GET&quot;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">post_install</span><span class="p">():</span>
    <span class="c1"># Verify the &quot;state&quot; parameter</span>

    <span class="c1"># Retrieve the auth code from the request params</span>
    <span class="n">code_param</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="s1">&#39;code&#39;</span><span class="p">]</span>

    <span class="c1"># An empty string is a valid token for this request</span>
    <span class="n">client</span> <span class="o">=</span> <span class="n">WebClient</span><span class="p">()</span>

    <span class="c1"># Request the auth tokens from Slack</span>
    <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">oauth_v2_access</span><span class="p">(</span>
        <span class="n">client_id</span><span class="o">=</span><span class="n">client_id</span><span class="p">,</span>
        <span class="n">client_secret</span><span class="o">=</span><span class="n">client_secret</span><span class="p">,</span>
        <span class="n">code</span><span class="o">=</span><span class="n">code_param</span>
    <span class="p">)</span>
</pre></div>
</div>
<p>A successful request to <code class="docutils literal notranslate"><span class="pre">oauth.v2.access</span></code> will yield a JSON payload with at least one token, a bot token that begins with <code class="docutils literal notranslate"><span class="pre">xoxb</span></code>.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/slack/oauth_redirect&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;GET&quot;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">post_install</span><span class="p">():</span>
    <span class="c1"># Verify the &quot;state&quot; parameter</span>

    <span class="c1"># Retrieve the auth code from the request params</span>
    <span class="n">code_param</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="s1">&#39;code&#39;</span><span class="p">]</span>

    <span class="c1"># An empty string is a valid token for this request</span>
    <span class="n">client</span> <span class="o">=</span> <span class="n">WebClient</span><span class="p">()</span>

    <span class="c1"># Request the auth tokens from Slack</span>
    <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">oauth_v2_access</span><span class="p">(</span>
        <span class="n">client_id</span><span class="o">=</span><span class="n">client_id</span><span class="p">,</span>
        <span class="n">client_secret</span><span class="o">=</span><span class="n">client_secret</span><span class="p">,</span>
        <span class="n">code</span><span class="o">=</span><span class="n">code_param</span>
    <span class="p">)</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>

    <span class="c1"># Save the bot token to an environmental variable or to your data store</span>
    <span class="c1"># for later use</span>
    <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;SLACK_BOT_TOKEN&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">response</span><span class="p">[</span><span class="s1">&#39;access_token&#39;</span><span class="p">]</span>

    <span class="c1"># Don&#39;t forget to let the user know that OAuth has succeeded!</span>
    <span class="k">return</span> <span class="s2">&quot;Installation is completed!&quot;</span>

<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
    <span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s2">&quot;localhost&quot;</span><span class="p">,</span> <span class="mi">3000</span><span class="p">)</span>
</pre></div>
</div>
<p>Once your user has completed the OAuth flow, you’ll be able to use the provided tokens to call any of Slack’s API methods that require an access token.</p>
<p>See the <a class="reference external" href="../basic_usage.html">Basic Usage</a> section of this documentation for usage examples.</p>
</section>
</section>


                        <div class="clear_both large_bottom_margin"></div>
                    </div>
                </div>
                <!-- /Body Content -->
            </div>
        </div>

        <footer>
            <p class="light tiny align_center">
                © 2015- Slack Technologies, LLC and contributors
            </p>
        </footer>

        <script>
            window.ga =
                window.ga ||
                function() {
                    (ga.q = ga.q || []).push(arguments);
                };
            ga.l = +new Date();
            ga('create', 'UA-56978219-13', 'auto');
            ga('send', 'pageview');
        </script>
        <script async src="https://www.google-analytics.com/analytics.js"></script>
    </body>
</html>